package com.shycloud.mido.common.security.component;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

import com.shycloud.mido.common.security.service.ShyMember;
import com.shycloud.mido.common.security.service.ShyOpterMember;
import com.shycloud.mido.common.security.service.ShyOrganMember;
import com.shycloud.mido.common.security.service.ShyUser;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
import org.springframework.util.StringUtils;

import cn.hutool.core.util.StrUtil;

/**
 * 根据checktoken 的结果转化用户信息
 *
 * @author nianhua.jiang
 * @date 2020/9/8 18:41
 **/
public class ShyUserAuthenticationConverter implements UserAuthenticationConverter {

	private static final String USER_ID = "user_id";
	private static final String ORGAN_ID = "organ_id";
	private static final String OPTER_ID = "opter_id";
	private static final String TYPE = "type";
	private static final String DEPT_ID = "dept_id";
	private static final String LOGIN_NAME = "username";
	private static final String PHONE = "phone";
	private static final String TENANT_ID = "tenant_id";
	private static final String N_A = "N/A";

	/**
	 * Extract information about the user to be used in an access token (i.e. for resource servers).
	 *
	 * @param authentication an authentication representing a user
	 * @return a map of key values representing the unique information about the user
	 */
	@Override
	public Map<String, ?> convertUserAuthentication(Authentication authentication) {
		Map<String, Object> response = new LinkedHashMap<>();
		response.put(USERNAME, authentication.getName());
		if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
			response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
		}
		return response;
	}

	/**
	 * Inverse of {@link #convertUserAuthentication(Authentication)}. Extracts an Authentication from a map.
	 *
	 * @param map a map of user information
	 * @return an Authentication representing the user or null if there is none
	 */
	@Override
	public Authentication extractAuthentication(Map<String, ?> map) {
		if (map.containsKey(USERNAME)) {
			String username = (String) map.get(USERNAME);

			if (StrUtil.startWithAny(username, "mobile@@")) {

				if (map.get("data") != null) {
					Map<String, Object> map2 = (Map<String, Object>) map.get("data");

					String id = (String) map2.get(USER_ID);
					String loginname = (String) map2.get(LOGIN_NAME);
					String phone = (String) map2.get(PHONE);
					Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
					ShyMember member = new ShyMember(id, loginname, phone, username, N_A, true
							, true, true, true, AuthorityUtils.NO_AUTHORITIES);
					return new UsernamePasswordAuthenticationToken(member, N_A, AuthorityUtils.NO_AUTHORITIES);
				}

				String id = (String) map.get(USER_ID);
				String loginname = (String) map.get(LOGIN_NAME);
				String phone = (String) map.get(PHONE);
				Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
				ShyMember member = new ShyMember(id, loginname, phone, username, N_A, true
						, true, true, true, AuthorityUtils.NO_AUTHORITIES);
				return new UsernamePasswordAuthenticationToken(member, N_A, AuthorityUtils.NO_AUTHORITIES);
			}

//			if (StrUtil.startWithAny(username, "wx@@")) {
//
//				Map<String, Object> map2 = (Map<String, Object>) map.get("data");
//
//				String id = (String) map2.get(USER_ID);
//				String loginname = (String) map2.get(LOGIN_NAME);
//				String phone = (String) map2.get(PHONE);
//				Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
//				ShyMember member = new ShyMember(id, loginname, phone, username, N_A, true
//						, true, true, true, AuthorityUtils.NO_AUTHORITIES);
//				return new UsernamePasswordAuthenticationToken(member, N_A, AuthorityUtils.NO_AUTHORITIES);
//			}

			if (StrUtil.startWithAny(username, "mini@@")) {
				String id = (String) map.get(USER_ID);
				String loginname = (String) map.get(LOGIN_NAME);
				String phone = (String) map.get(PHONE);
				Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
				ShyMember member = new ShyMember(id, loginname, phone, username, N_A, true
						, true, true, true, AuthorityUtils.NO_AUTHORITIES);
				return new UsernamePasswordAuthenticationToken(member, N_A, AuthorityUtils.NO_AUTHORITIES);
			}

			if (StrUtil.startWithAny(username, "organ@@")) {
				String id = (String) map.get(USER_ID);
				String organId = (String) map.get(ORGAN_ID);
				String type = (String) map.get(TYPE);
				Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
				ShyOrganMember member = new ShyOrganMember(id, organId, type, username, N_A, true
						, true, true, true, AuthorityUtils.NO_AUTHORITIES);
				return new UsernamePasswordAuthenticationToken(member, N_A, AuthorityUtils.NO_AUTHORITIES);
			}

			if (StrUtil.startWithAny(username, "opter@@")) {
				String id = (String) map.get(USER_ID);
				String opterId = (String) map.get(OPTER_ID);
				Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
				ShyOpterMember member = new ShyOpterMember(id, opterId, username, N_A, true
						, true, true, true, AuthorityUtils.NO_AUTHORITIES);
				return new UsernamePasswordAuthenticationToken(member, N_A, AuthorityUtils.NO_AUTHORITIES);
			}

			Integer id = (Integer) map.get(USER_ID);
			Integer deptId = (Integer) map.get(DEPT_ID);
			Integer tenantId = (Integer) map.get(TENANT_ID);
			Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
			//获取roleId
			Integer roleId = 0;
			ShyUser user = new ShyUser(id, deptId, tenantId, username, N_A, roleId, true
					, true, true, true, authorities);
			return new UsernamePasswordAuthenticationToken(user, N_A, authorities);
		}
		return null;
	}

	private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
		Object authorities = map.get(AUTHORITIES);
		if (authorities == null) {
			return AuthorityUtils.NO_AUTHORITIES;
		}
		if (authorities instanceof String) {
			return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
		}
		if (authorities instanceof Collection) {
			return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils
					.collectionToCommaDelimitedString((Collection<?>) authorities));
		}
		throw new IllegalArgumentException("Authorities must be either a String or a Collection");
	}
}